Skip to content

Dear ImGui port of Image Viewer (imiv) with Vulkan/Metal/OpenGL backends for Windowns/Linux/MacOS#5125

Open
ssh4net wants to merge 512 commits intoAcademySoftwareFoundation:mainfrom
ssh4net:_imgui
Open

Dear ImGui port of Image Viewer (imiv) with Vulkan/Metal/OpenGL backends for Windowns/Linux/MacOS#5125
ssh4net wants to merge 512 commits intoAcademySoftwareFoundation:mainfrom
ssh4net:_imgui

Conversation

@ssh4net
Copy link
Copy Markdown
Contributor

@ssh4net ssh4net commented Apr 1, 2026

image

Description

This PR adds imiv to OpenImageIO as a full application, with its own build integration, documentation, and test coverage.
The goal here is to upstream the whole app in a usable state rather than split it into a long series of smaller PRs.

What is included:

  • the new src/imiv/ application and CMake integration
  • renderer backends for:
    • Vulkan
    • OpenGL
    • Metal
  • runtime backend selection, probing, and preferences UI
  • OCIO preview support across the supported backends
  • Dear ImGui Test Engine integration and Python-based GUI regression tooling
  • backend verification tools for macOS, Windows, and Linux/WSL
  • multi-image workflows:
    • startup multi-open
    • drag and drop
    • Open Folder...
    • docked Image List
    • multi-view image windows
  • per-view preview state:
    • exposure
    • gamma
    • shift
    • interpolation
    • channel/display mode
    • OCIO display/view/image color space
  • GUI-driven CPU export paths:
    • Save As...
    • Save Selection As...
    • Export As...
    • Export Selection As...
  • embedded runtime assets for:
    • DroidSans.ttf
    • DroidSansMono.ttf
    • static Vulkan upload/preview SPIR-V shaders
  • user, developer, and test documentation for imiv

A few implementation notes that are probably useful to reviewers:

  • Vulkan remains the reference backend for renderer-side behavior.
  • OpenGL and Metal follow the same viewer semantics using native backend paths.
  • Static Vulkan shaders are embedded at build time, but OCIO shader generation remains runtime-driven.
  • Recent work also hardened large-image upload and backend switching behavior, especially around Vulkan resource lifetime and cross-backend verification.

This is meant to be the first upstreamable version of imiv, not the last word on its architecture. There is still room for follow-up work, especially around larger-image tiling/proxy paths and longer-term refinement, but the app is now in a shape where it can be reviewed and used as part of the tree.

Warning: This project heavily used Codex GPT5.4 in Extra High, but the Vulkan and OpenGL integration of the image viewer itself is based on my personal projects and prior experience in similar tools.

In a project, working time code multiply times was passed a code review using an alternative LLM like Opus 4.6 to avoid single model bias. The issues found at that time were fixed.

I have not polished the GUI layout, and some proper use of ImGui Table/Forms is still needed to make the GUI better respond to layouts.

Tests

This PR adds a dedicated imiv regression suite built around Dear ImGui Test Engine, plus backend-level verification tools.

Coverage includes focused GUI regressions for:

  • navigation and UX actions
  • selection and area probe
  • RGB input handling
  • sampling / interpolation
  • drag and drop
  • Open Folder...
  • multi-view and Image List
  • backend preferences
  • OCIO fallback / config source / live update / live display
  • export and selection export paths
  • large-image switching

It also includes shared backend verifier coverage for:

  • smoke
  • rgb
  • ux
  • sampling
  • ocio_missing
  • ocio_config_source
  • ocio_live
  • ocio_live_display

Validation was done on the current development platforms:

  • macOS:
    • shared backend verifier passes on Metal, OpenGL, and Vulkan
  • Linux / WSL:
    • combined Vulkan + OpenGL build validated with focused regressions and backend verification
  • Windows:
    • Vulkan and OpenGL were validated through current regression and manual bring-up paths, including folder-open and multi-image workflows

New dependencies:

Required / core for imiv

Optional but imiv-specific

Vendored helper in imiv

  • dnd_glfw
    • In-tree: src/imiv/external/dnd_glfw (Repo: https://github.com/ssh4net/dnd_glfw)
    • Reason: richer drag-and-drop behavior around GLFW, especially drag-enter / drag-over / drag-leave overlay handling on Windows/Linux and macOS.

Checklist:

  • I have read the guidelines on contributions and code review procedures.
  • I have read the Policy on AI Coding Assistants
    and I have used AI coding assistants Codex CLI/ Codex GPT5.4 Extra High
  • I have updated the documentation if my PR adds features or changes
    behavior.
  • I am sure that this PR's changes are tested in the testsuite.
  • I have run and passed the testsuite in CI before submitting the
    PR, by pushing the changes to my fork and seeing that the automated CI
    passed there. (Exceptions: If most tests pass and you can't figure out why
    the remaining ones fail, it's ok to submit the PR and ask for help. Or if
    any failures seem entirely unrelated to your change; sometimes things break
    on the GitHub runners.)
  • My code follows the prevailing code style of this project and I
    fixed any problems reported by the clang-format CI test.
  • If I added or modified a public C++ API call, I have also amended the
    corresponding Python bindings. If altering ImageBufAlgo functions, I also
    exposed the new functionality as oiiotool options.

@lgritz
Copy link
Copy Markdown
Collaborator

lgritz commented Apr 1, 2026

It looks like you have been working on this branch for a while and lots has diverged. Can you please rebase on top of the current main?

brechtvl and others added 27 commits April 2, 2026 13:34
…pace (AcademySoftwareFoundation#4967)

If the colorspace exists and has an interop ID in an OCIO 2.5 config,
use that.
Otherwise check if the colorspace is equivalent to a known color interop
ID.

Tests were added.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…undation#4968)

The JPEG XL color encoding metadata only supports a subset of CICP. So
for
example `srgb_p3d65_display` and `pq_rec2020_display` are supported, but
`g26_xyzd65_display` is not.

Custom primaries, custom white point and arbitrary gamma could be used
to
support more, but I didn't implement that.

Tests for read and write were added.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…()` (AcademySoftwareFoundation#4987)

Rearrangements in 3.1 dropped the list of recognized attributes from
the visible online docs and failed to document the span varieties. We
fix and also reword a lot of the descriptions for clarity and uniformity.

The previous organization was that there were several varieties of attribute(). In the header, the first one had the overall long explanation, including the list of all the recognized attributes. The other ones had short explanations of how they differed. In the docs, each one was referenced explicitly, pulling in its attendant bit of documentation.

What really happened is that in the header, I made the new span-based version the "flagship" one with the full explanation, but I neglected to reference it in the docs, so the long description disappeared.

I could have fixed by just adding refs to the new functions to the docs, as I originally meant to. But while I was there, I took the opportunity to surround the whole collection with a group marker, and then include the lot of them with a single reference to the group, rather than need to refer to each function variant individually. And while I was at it, I also reworded (and hopefully improved) some of those explanations.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…Foundation#4990)

Implement RLE compression support for the SGI output plugin. Reading RLE
encoded images was already supported, but writing was never done up
until this point.

The existing sgi test seems sufficient to catch issues and it covers
input/output of both 1 byte-per-pixel and 2 byte-per-pixel files.

The documentation for the image plugins are sometimes not very clear
about which attributes are relevant for input vs. output. There's
usually 3 sections: Attributes, Attributes for Input, and Attributes for
Output.

Before this PR, SGI mentioned the "compression" attribute in the
"general" Attributes section (rather than say just the Input section),
which caused a bit of grief as the only way to discover that RLE was not
implemented for Output was to glance at the file size of the resulting
file... I had assumed that compression was supported for output too but
discovered that it was not.

Now that this PR implements the attribute for output I've left the
documentation as-is in the "general" Attributes section since it applies
to both read/writing now. But I'm open for suggestions here.

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
Starting with 1.21, libheif seems to change behavior: When no CICP
metadata is present, libheif now returns 2,2,2 (all unspecified) on
read. OIIO convention, though, is to not set the attribute if valid CICP
data is not in the file.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…wareFoundation#4993)

For IBA::resample() when bilinear interpolation is used, almost all of
the expense was due to its relying on ImageBuf::interppixel which is
simple but constructs a new ImageBuf::ConstIterator EVERY TIME, which is
very expensive.

Reimplement in a way that reuses a single iterator. This speeds up
IBA::resample by 20x or more typicaly.

Also refactor resample to pull the handling of deep images into a
separate helper function and out of the main inner loop. And add some
benchmarking.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
* CI test vs the latest freetype 2.14.1
* Bump the version of freetype that we auto-build to the latest (from
2.13.2)
* Simplify BZip2 finding logic, switch to using targets

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…areFoundation#4998)

The Intel MacOS 15 CI testing is getting dicier... lots of times,
Homebrew doesn't have cached versions of updated packages, so it tries
to build from source, which takes forever. The big culprit today is Qt.
So, basically, just on this one CI job variant, don't ask it to install
Qt. If it's there, it's there. If not, just skip it. It's tested plenty
in other variants.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…cademySoftwareFoundation#4997)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
Fixes AcademySoftwareFoundation#5000

Signed-off-by: Brad Smith <brad@comstyle.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…wareFoundation#4995)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
Due to typos in the option name in compiler.cmake (HARDENING vs
OIIO_HARDENING, oops), I think we were never really setting the intended
compiler flags. Fix that all up, and repair the other problems that it
revealed -- some compiler version and option combinations weren't happy
with each other, etc.

One notable change is in encode_iptc_iim_one_tag: I think I made it
safer by taking an early out for 0-sized data, and also it needed a
warning suppression when certain gcc hardening levels were used.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
Needed for some systems after the changes of AcademySoftwareFoundation#4963.

Ever so slightly different LSB somewhere makes the hashes not match, but
it's a correct visual result.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…eFoundation#5008)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…ftwareFoundation#5010)

Yay, I love how these things just break with no notice.

Fixes CI that broke a couple days agi.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…areFoundation#5009)

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…SoftwareFoundation#5004)

* ImageBuf internal buffer span lacked correct chansize. The internal
`m_bufspan` is an `image_span<byte>`, and as such, it needs to remember
the size of the original data type. Otherwise, there's a cascade of
potential errors when it thinks that the individual values are byte
sized.

* In both ImageInput and ImageOutput, several sanity checks of
image_span size versus expectations were incorrect. They were only
checking if the total byte sizes matched expectations, but they are
allowed to disagree when you consider type conversions (in which case,
it's the total number of values that need to match, not the total byte
sizes.

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…ation#5012)

Needed to change the Libheif::Libheif target we set up ages ago to the
"heif" name that the package's exported config uses.

Also, need to give the warning about static libraries occur any time we
are using static libheif, even if we didn't set LIBSTATIC to try to
force all static libraries.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…ng (AcademySoftwareFoundation#5005)

We previously merely *marked* tests as "broken" in this case, and
depended on ctest being launched with `-E broken` to ensure those were
skipped. Not everybody did. Let's just truly skip them.

Fixes AcademySoftwareFoundation#4979

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…emySoftwareFoundation#5013)

Initializing the encoder to `heif_compression_HEVC` by default throws an
exception when libheif was built without HEVC support, which prevents it
from being used entirely even if there is AVIF support.

So delay that initialization until we are sure which encoding we want.

Not really any practical way to automatically test this.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…ySoftwareFoundation#5016)

The WebP format is very limited in the maximum resolution it supports.
We need to change the values we allow to be much smaller.

Signed-off-by: Jesse Yurkovich <jesse.y@gmail.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…areFoundation#5014)

Nearly all IBA functions take an optional parameter controlling the
threading. But make_texture() did not, so there was no way to control
its thread usage (it would always use the default number of threads).

Without changing the call signature or ABI, this patch merely makes
make_texture honor any "maketx:threads" hint passed in the config
ImageSpec that it already takes to convey all sorts of controls over the
texture creation process. Then this value is passed to any IBA
functions, use of parallel_image, and anything else in the
implementation of make_texture that would end up using the thread pool.

Fixes AcademySoftwareFoundation#4254

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…SoftwareFoundation#5011)

Utilities to ask the IB for the local pixels as an untyped span of
bytes. This is a "safe" alternative to `localpixels()`, which just
returned a single pointer, instead returning an image_span that
understands the sizes and strides of the buffer.

---------

Signed-off-by: Larry Gritz <lg@larrygritz.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…ademySoftwareFoundation#5018)

This variable should not have been static.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
…on#5017)

Add IOProxy support similar to other file formats.

MyHeifWriter was renamed for consistency with other code.

All input and output now goes through the proxy, so this is covered by
existing tests.

Signed-off-by: Brecht Van Lommel <brecht@blender.org>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
Copy link
Copy Markdown
Collaborator

@lgritz lgritz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a first set of comments on a few organizational things. It's a lot to review, and I haven't really dug into the meat of the code yet. We'll do a little bit at a time.

@@ -1,5 +1,4 @@
Policy on AI Coding Assistants
==============================
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one of several spots where something unrelated to this PR seems to have changed for no reason.

Comment on lines +85 to +91
# Helper: record the final status of a dependency that is discovered outside
# checked_find_package(), so it still shows up in the dependency summary.
macro (record_build_dependency pkgname)
cmake_parse_arguments(_pkg
"FOUND;NOTFOUND;REQUIRED"
"VERSION;NOT_FOUND_EXPLANATION"
""
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's with all the changes here?

# Note: If this tag is empty the current directory is searched.

INPUT = ../../src
INPUT = ../../src/include/OpenImageIO
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where the contents of Doxyfile changed on purpose?

Comment on lines +58 to +60
imiv_user
imiv_dev
imiv_tests
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think only the user documentation should be in src/doc and appear in the ReadTheDocs page that explains how users should use OIIO. I believe the developer documentation (contents of imiv_dev and imiv_tests, I believe) should go in docs/dev with the rest of the developer documentation that explains how we develop the code.

Comment on lines +1 to +4
# dnd_glfw – GLFW Drag-and-Drop Helper

`dnd_glfw` is a very small helper around GLFW that exposes a simple, C‑style drag‑and‑drop callback interface. It is designed for applications that already use GLFW for their main window (e.g. Dear ImGui with the GLFW/OpenGL backend) and want better control over file drops and drag‑hover overlays.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is dnd_glfw an existing external project? Oh, I see: https://github.com/ssh4net/dnd_glfw
You should definitely reference that here, and point out that the reason we're keeping this in a separate external/ directory is so that new versions of the external one can just be dropped in, so it's not too mixed with the rest of the code that might drift separately?

I think it would be helpful for the periodic license scanning, if the dnd_glfw file had at their top the same kind of // SPDX-License-Identifier: MIT identifier and copyright notice (though with your name, if you are the external author).

/*.log


/build_*
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this file change?

add_subdirectory (src/igrep)
add_subdirectory (src/iinfo)
add_subdirectory (src/imiv)
add_subdirectory (src/maketx)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is fine, but about 10 lines higher up, you probably need an ENABLE_imiv switch for the SKBUILD case.

(GitHub reviews unfortunately do not line you add comments to code that didn't change, even if you are just trying to point a place that SHOULD have changed!)

OpenImageIO
$<TARGET_NAME_IF_EXISTS:OpenColorIO::OpenColorIO>
$<TARGET_NAME_IF_EXISTS:OpenColorIO::OpenColorIOHeaders>)
find_package (glfw3 CONFIG QUIET)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can all of the find_package file in this file just be changed to checked_find_package, gain all the extra features that provides, and then you don't need to add record_build_dependency or other changes to dependency_utils.cmake?

Copy link
Copy Markdown
Collaborator

@lgritz lgritz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imiv/CMakeLists.txt is absolutely enormous! Is there any way that it can be simplified?

@lgritz
Copy link
Copy Markdown
Collaborator

lgritz commented Apr 5, 2026

I've never programmed for Dear Imgui before, so I don't know if what I'm asking is naive. Maybe I am misunderstanding how Imgui projects are typically structured. But the amount of code and even the number of added source code modules is absolutely humongous compared to the existing iv.

Old iv using Qt:

  • 12 files (*.cpp, *.h, CMakeLists.txt) containing 7042 lines of code
  • admittedly, has no tests

New iv using Dear ImGUI:

  • 74 files containing 33181 lines for the implementation
  • Plus another 41 files containing 12981 lines just for testing infrastructure and tooling

Does this seem right? Does a fairly simple image viewer need so much boilerplate with Imgui that it's nearly 5x more implementation code than the equivalent app using Qt (plus an additional 1.5x for testing infrastructure)?

That feels off to me, but that's just my intuition. If you had asked me beforehand what I expected the imgui version of iv to be like, I would have guessed that it would be similar size and complexity as the old Qt one (maybe I could even hoped for some kind of simplification?), but bringing the advantage of allowing us to drop Qt as a dependency (which is a small but concrete benefit to builders, because Qt is so huge and onerous to build). It's an entirely different set of tradeoffs to consider if the cost of dropping Qt is a 5x increase in OIIO-side implementation code size for the viewer app.

@ssh4net
Copy link
Copy Markdown
Contributor Author

ssh4net commented Apr 6, 2026

@lgritz imgui for sure need more boilerplate, especially Vulkan backend or support multiply backends. But I will check if a code base can be reduced.
Qt for sure has own advantages that you need write less for basic GUI.

@lgritz
Copy link
Copy Markdown
Collaborator

lgritz commented Apr 6, 2026

New iv using Dear ImGUI:
* 74 files containing 33181 lines for the implementation
* Plus another 41 files containing 12981 lines just for testing infrastructure and tooling

Contrasting data point: https://github.com/wkjarosz/hdrview
This is also an ImGui-based image viewer, not too dissimilar to iv (though undoubtedly nicer and more feature rich, so should be more code than us).

It has a total of 133 source files, 47,140 LOC. It doesn't use OIIO or a similar comprehensive format library, so it has a lot of code dedicated to reading the formats (37 source files, 12069 lines). Excluding that, then, the total is 96 files, 35k LOC.)

With those high-level stats, it could be that it proves that it's roughly the same size as Vlad's imiv, and that's just what is to be expected for an ImGui-based viewer. Or it could be that only a small subset of those 35k LOC are directly related to ImGui, indicating that we're being much more repetitive and verbose than needed?

Might be worth a look to see what they're doing.

@lgritz
Copy link
Copy Markdown
Collaborator

lgritz commented Apr 6, 2026

By the way, given the existence of hdrview and other very nice viewers, one might be tempted to ask, "Does OIIO need a viewer at all?" And also, "if so, how good does it need to be?" is important when evaluating tradeoffs like this PR.

Here is my answer. The goals of iv are:

  • To be able to view any format, and any feature of that format, that OIIO can read. That's hard to control for other viewers. (As an example, the very nice hdrview can't read DPX files.)
  • It's helpful to have specialized tools that aren't available in other viewers. (Example: most viewers don't let you examine individual MIP levels of a texture, or channels beyond RGBA, but we need this to validate if OIIO is reading and writing those properly.)
  • For debugging, it's helpful to directly visualize the data coming through OIIO's APIs, especially when something is going wrong.
  • To have at least a minimal viewer available to anybody who builds OIIO.
  • To have a second, independent viewer code path to validate, and compare to, other viewers.

So, then, it's primarily a validation and debugging tool for OIIO itself (and therefore still necessary, IMHO). And secondarily, people may find it a good viewer in its own right, if their needs aren't too strenuous, but we are not trying to make it a comprehensive, production-quality studio viewer (and therefore, there is a point of diminishing returns on added complexity and ongoing maintenance cost).

@ssh4net
Copy link
Copy Markdown
Contributor Author

ssh4net commented Apr 7, 2026

Yes, @lgritz, I also always was in thoughs is oiio should have a full-featured image viewer, when a proper GUI app required a lot of attention. And got carried away from the original idea, making only the OpenGL version, with all that multi-backend fun.
I will close this commit, and do not think this work was a waste of resources, as I definitely will use a lot of findings from it in my other projects 😉

@ssh4net ssh4net closed this Apr 7, 2026
@lgritz
Copy link
Copy Markdown
Collaborator

lgritz commented Apr 7, 2026

Wait, are you being too hasty here? I was not necessarily implying that we shouldn't pursue this, and definitely wasn't prodding you to close this PR.

I'm still trying to understand a basic question -- can iv switch to a lighter-weight dependency than Qt, without it somehow exploding the amount of code we have to maintain by a large factor? I think there's merit to dropping Qt for something simpler, as long as there is not too high a cost imposed somewhere else.

There also is merit to improving iv. I'm definitely not against that, it's just a matter of cost for benefit, and what we mean by "improve." Two things to say about this:

  1. It may be one thing to say "we don't want to divert resources to iv at the expense of our core goals", but if new resources come just for iv (say, somebody who is willing to put that effort in, not at the expense of things others are committed to doing elsewhere), that changes the calculus. Phrased another way: there's a difference between somebody asking for iv to be better and our reply needing to be "it's not a priority", versus somebody coming to us and saying "I will do that work to make iv better." Different situations entirely.
  2. There is an enormous gulf between the capabilities of iv and the kind of viewer that we use in a big studio like where I work. I don't want OIIO becoming a project dominated by making that kind of tool. But it's possible that somebody could hear me say "we don't want iv to be that" and mistakenly think I mean "we don't want iv to be better", but those are really two very different things. I'm all for it improving substantially at displaying and examining still images. I don't think it should be an image editing tool like Lightroom, or a studio-quality media and review tool like OpenRV. We're the wrong project for either of those.

@ssh4net
Copy link
Copy Markdown
Contributor Author

ssh4net commented Apr 7, 2026

For sure, something that should be a simple image viewer becomes overcomplicated.
Qt has a huge advantage in that it hides a lot of low-level control from a coder. Maybe in the scope of OIIO, Qt was the right choice.
So i don't know...
I still try to refactor the code, but don't see yet if it's possible to halve the LOC.

@lgritz
Copy link
Copy Markdown
Collaborator

lgritz commented Apr 7, 2026

I'm curious what you think if you take a quick skim of hdrview. Do you look at that and think "yeah, looks roughly the same as imiv", or do you think "wow, they made the imgui parts much smaller"? I don't know enough about imgui to make the judgment myself, I don't know what to look for.

I know that lots of projects really like imgui and I've heard great things about it. I don't recall anybody saying "but OMG it makes the code 5x bigger". But maybe everybody but me already understands that and it doesn't need to be said out loud?

@lgritz
Copy link
Copy Markdown
Collaborator

lgritz commented Apr 7, 2026

Maybe in the scope of OIIO, Qt was the right choice.

Could be. But if so, it's kinda coincidence. When I wrote iv in early 2008, I think the only toolkits that seemed capable and cross-platform at that time were Qt, WxWidgets, and Fltk. I'd used fltk before, but it seemed kind of old fashioned. I picked Qt somewhat arbitrarily, and because I knew that in vfx, it was becoming more common. Since then, it's just been inertia. Lots of other GUI toolkits have popped up (including ImGui), and I never stopped to directly compare them. We are not using Qt for any principled reason.

@ssh4net
Copy link
Copy Markdown
Contributor Author

ssh4net commented Apr 7, 2026

I will review Imiv with HDRiview. Maybe i missing something in a logic.

@ssh4net
Copy link
Copy Markdown
Contributor Author

ssh4net commented Apr 7, 2026

@lgritz looks like Hdrview is heavily related to the HelloImGui and ImPlot libraries, which are themselves layer libraries on top of ImGui. Personally, I slightly fear relating to the ImGui 3rd-party libraries as they are not maintained as well as ImGui itself.
Also, at this moment, ImGui does not look like it provides such fine-grained control for Metal texture creation, and this is a reason why imiv has quite a big mm file with Metal code (mainly to enable/disable interpolation). I thought to check how this was made and maybe propose these changes to the ImGui project.
So overall, yes, ImGui has more LOC, but some of them are from native ImGui use, ImGui Test Engine hooks, and regression tests hooks.

@lgritz
Copy link
Copy Markdown
Collaborator

lgritz commented Apr 7, 2026

I'm going to re-open this. Let's just let it sit for a while and gather other people's opinions before deciding if this is a tradeoff that makes sense for us in the long run.

@lgritz lgritz reopened this Apr 7, 2026
ssh4net added 4 commits April 7, 2026 21:32
Move large imiv source, shader and test lists out of src/imiv/CMakeLists.txt into dedicated cmake/imiv_sources.cmake and cmake/imiv_tests.cmake and include them from CMakeLists. This extracts shared_sources, platform/renderer source groups, shader embedding/custom-command helpers, font embedding logic and test registrations to improve CMake organization and readability. Also adds a number of new imiv source/header files (actions, developer tools, file actions, image library, persistence/parse, Vulkan helpers, preview shader text, probe overlay, workspace UI, etc.) referenced by the new cmake files.

Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Pass the underlying C string to +[NSString stringWithUTF8String:] instead of the std::string object. This fixes an incorrect/ambiguous conversion when creating the Metal shader source NSString in the renderer.

Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
Add SPDX headers. Reformat and tidy dnd_glfw.h (includes, spacing, inline function layout, and minor Windows DropTarget refactor) without changing public API. On macOS, stop registering NSFilenamesPboardType and adjust cocoaView bridging to use manual cast/release (fixes retain/release semantics). Small adjustment to GLFW drop-callback setup/assignment formatting.

Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Signed-off-by: Vlad <shaamaan@gmail.com>
Introduce helper utilities and refactor duplicated Metal OCIO logic: add create_default_compile_options and create_ocio_compile_options; add begin_offscreen_render_pass and end_offscreen_render_pass to centralize command buffer/encoder lifecycle; introduce MetalOcioShaderSourceParts and helper builders (append_ocio_* / build_ocio_shader_call_params / append_texture_binding_source) to construct OCIO shader sources and call parameters; factor texture upload loops into upload_ocio_textures_for_dimension and upload_ocio_non_3d_textures; add bind_ocio_fragment_resources to bind fragment uniforms/textures. Update preview pipeline and OCIO preview program to use these helpers, reducing duplication and improving clarity and error handling.

Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
ssh4net and others added 8 commits April 8, 2026 11:40
Move all image save/export functionality out of imiv_file_actions.cpp into a new imiv_image_save.cpp/.h pair to separate responsibilities and reduce file size. Update imiv_file_actions.cpp to include the new header and remove the duplicated save/build helpers. Add imgui_stdlib (imgui_stdlib.cpp/header) to CMake source lists and use ImGui::InputText(std::string) in imiv_ui.cpp (replace manual buffer handling). Also add /bld to .gitignore and register the new source file in imiv_sources.cmake/CMakeLists.txt.

Signed-off-by: Vlad <shaamaan@gmail.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Add a new Image List UI (imiv_image_list_ui.*) and a dedicated Preferences window (imiv_preferences_window.cpp), and wire them into the build (imiv_sources.cmake). Replace the previous image_window_title function with an inline constexpr k_image_window_title and update call sites. Move large preference-related UI code out of imiv_aux_windows.cpp into the new preferences file and clean up related helper functions. Update persistence paths to use string literals for legacy filenames, and adjust includes across several modules (developer tools, frame, etc.) to reference the new headers. Also include minor adjustments to test-engine hooks to use the new image title constant and other housekeeping to integrate the new UI components.

Signed-off-by: Vlad <shaamaan@gmail.com>
Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com>
Remove small per-backend wrapper functions and wire the vtables to the real ImGui functions and existing helpers. Added renderer_noop_wait_idle and a renderer_call_backend_new_frame template in the header to avoid duplicated no-op/new-frame wrappers. Updated Metal, OpenGL and Vulkan backends to use ImGui_Impl* Shutdown/NewFrame directly and to reference existing functions (e.g. platform_glfw_supports_vulkan, imiv_vulkan_screen_capture). This reduces boilerplate and keeps behavior unchanged.

Signed-off-by: Vlad <shaamaan@gmail.com>
Refactor UI and build sources: remove legacy backend/workspace/image-list/save/vulkan-window modules and update CMake source lists accordingly. Move/centralize preferences UI into imiv_aux_windows.cpp (theme, pixel view, image rendering, OCIO config, backend selector, memory, slideshow and close behavior) and update documentation to reference imiv_vulkan_setup. Add image export/save and OCIO-aware processing routines to imiv_file_actions.cpp and adjust includes across several modules to use imiv_viewer/imiv_workspace_ui. Overall cleanup to consolidate preference, export, and backend selection logic and remove obsolete files.

Signed-off-by: Vlad <shaamaan@gmail.com>
helper functions to obtain/validate backend state (ensure_opengl_backend_state, opengl_window_state, ensure_vulkan_backend_state, vulkan_backend_state) and consolidate repeated null/initialization checks. Replace many explicit backend setup/teardown functions with inline lambdas in the renderer vtables, reducing duplicated code for instance/device/window/surface setup, context backup/restore, frame present and cleanup. Also standardize framebuffer size handling (use renderer_set_framebuffer_size) and adjust texture/create/update flows to use the new helpers and clearer error messages. Overall this simplifies control flow and centralizes error handling for OpenGL and Vulkan backends.

Signed-off-by: Vlad <shaamaan@gmail.com>
Introduce imiv_upload_corpus_smoke.py: a new Python driver that runs batched upload smoke tests by generating per-batch scenarios, invoking the GUI test runner, collecting screenshots and state JSON, validating results, and writing a summary CSV. Update imiv_upload_corpus_smoke_test.sh to call the new driver with batch/timeout options and sensible defaults. Refactor imiv_auto_subimage_regression.py to remove the old internal _run_case helper and add a "baseline" scenario step (and include it when collecting scenario states), so the baseline is produced via the scenario runner rather than a separate invocation. Overall this consolidates per-image logic into a batched workflow and simplifies test orchestration.

Signed-off-by: Vlad <shaamaan@gmail.com>
Create_buffer_resource and create_buffer_with_memory_resource plus make_color_image_memory_barrier to centralize buffer creation, memory allocation/binding and common image memory barrier setup. Replace repeated vkCreateBuffer/allocate_and_bind_buffer_memory and manual VkImageMemoryBarrier constructions across OCIO, preview and texture code with the new helpers to reduce duplication, improve readability, and preserve existing error reporting and debug naming. Updated headers and call sites in imiv_vulkan_ocio.cpp, imiv_vulkan_preview.cpp, imiv_vulkan_texture.cpp and resource utils files accordingly.

Signed-off-by: Vlad <shaamaan@gmail.com>
Include pixel probe info in test state output and make Vulkan resource management more robust.

- imiv_developer_tools.cpp: Write probe fields (probe_valid, probe_pos, probe_channel_count) into the test-engine JSON output so runner tests can inspect probe state.
- imiv_image_view.cpp: Use env_read_int_value to fetch forced probe coordinates and simplify validation logic.
- imiv_vulkan_setup.cpp: Factor repeated destroy logic into small helper functions (shader module, pipeline, pipeline layout, descriptor set layout, descriptor pool, render pass) and use them across cleanup paths; change init_* functions to build resources in a linear, transactional manner (do-break cleanup) so partial failures clean up correctly; ensure shader modules are destroyed on failure and centralize descriptor pool destruction.
- tools/imiv_area_probe_closeup_regression.py: Add _run_runner helper and a two-step test flow: run a pixel-closeup probe to capture probe state JSON (validate probe_valid and probe_pos), then run the area-probe closeup runner. Also add probe_state_path and related checks.

These changes improve testability of the pixel probe feature and harden Vulkan resource lifecycle handling to avoid leaks on error paths.

Signed-off-by: Vlad <shaamaan@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.